home *** CD-ROM | disk | FTP | other *** search
- /*ScianSnap.c
- Eric Pepke
- 14 January 1993
-
- Routines for variable snapshots in SciAn
- */
-
- #include "Scian.h"
- #include "ScianTypes.h"
- #include "ScianIDs.h"
- #include "ScianLists.h"
- #include "ScianArrays.h"
- #include "ScianErrors.h"
- #include "ScianSnap.h"
- #include "ScianWindows.h"
- #include "ScianObjWindows.h"
- #include "ScianControls.h"
- #include "ScianSymbols.h"
- #include "ScianGarbageMan.h"
- #include "ScianMethods.h"
- #include "ScianDatabase.h"
- #include "ScianDepend.h"
- #include "ScianTextFiles.h"
- #include "ScianScripts.h"
-
- ObjPtr snapshotClass; /*Class for all snapshots*/
-
- #ifdef PROTO
- void AddSnapVar(ObjPtr object, NameTyp var)
- #else
- void AddSnapVar(object, var)
- ObjPtr object;
- NameTyp var;
- #endif
- /*Adds a snap var to object*/
- {
- ObjPtr snapVars;
-
- snapVars = Get1Var(object, SNAPVARS);
-
- if (!snapVars)
- {
- snapVars = NewList();
- }
-
- PostfixList(snapVars, NewSymbol(var));
- SetVar(object, SNAPVARS, snapVars);
- }
-
- #ifdef PROTO
- ObjPtr AssembleSnapVars(ObjPtr object)
- #else
- ObjPtr AssembleSnapVars(object)
- ObjPtr object;
- #endif
- /*Assembles some snap vars from object, superclass first*/
- {
- if (object)
- {
- ObjPtr retVal;
- ObjPtr curSnapVars;
- ThingListPtr runner;
-
- retVal = AssembleSnapVars(ClassOf(object));
- curSnapVars = Get1Var(object, SNAPVARS);
- if (curSnapVars && IsList(curSnapVars))
- {
- if (!retVal)
- {
- retVal = NewList();
- }
- for (runner = LISTOF(curSnapVars); runner; runner = runner -> next)
- {
- if (WhichListIndex(retVal, runner -> thing) < 0)
- {
- PostfixList(retVal, runner -> thing);
- }
- }
- }
- return retVal;
- }
- else
- {
- return NULLOBJ;
- }
- }
-
- #ifdef PROTO
- ObjPtr TakeSnapshot(ObjPtr object)
- #else
- ObjPtr TakeSnapshot(object)
- ObjPtr object;
- #endif
- /*Takes a snapshot of object*/
- {
- ObjPtr list;
- ObjPtr retVal;
-
- /*Make the snap vars*/
- list = AssembleSnapVars(object);
-
- retVal = NewObject(snapshotClass, 0L);
- SetVar(retVal, REPOBJ, object);
- SetVar(retVal, SNAPVARS, list);
- if (list)
- {
- ThingListPtr runner;
-
- runner = LISTOF(list);
- while (runner)
- {
- NameTyp id;
-
- id = GetSymbolID(runner -> thing);
- if (id)
- {
- MakeVar(object, id);
- SetVar(retVal, id, GetVar(object, id));
- }
- runner = runner -> next;
- }
- }
- SetVar(retVal, NAME, GetVar(object, NAME));
- SetVar(retVal, REPCLASSID, GetVar(object, CLASSID));
-
- return retVal;
- }
-
- #ifdef PROTO
- ObjPtr TakeVarsSnapshot(ObjPtr object, ObjPtr list)
- #else
- ObjPtr TakeVarsSnapshot(object)
- ObjPtr object;
- #endif
- /*Takes a snapshot of object, the variables in list.*/
- {
- ObjPtr retVal;
-
- retVal = NewObject(snapshotClass, 0L);
- SetVar(retVal, REPOBJ, object);
- SetVar(retVal, SNAPVARS, list);
- if (list)
- {
- ThingListPtr runner;
-
- runner = LISTOF(list);
- while (runner)
- {
- NameTyp id;
-
- id = GetSymbolID(runner -> thing);
- if (id)
- {
- MakeVar(object, id);
- SetVar(retVal, id, GetVar(object, id));
- }
- runner = runner -> next;
- }
- }
- SetVar(retVal, NAME, GetVar(object, NAME));
- SetVar(retVal, REPCLASSID, GetVar(object, CLASSID));
-
- return retVal;
- }
-
- #ifdef PROTO
- ObjPtr TakeSingleVarSnapshot(ObjPtr object, NameTyp whichVar)
- #else
- ObjPtr TakeSingleVarSnapshot(object, whichVar)
- ObjPtr object;
- NameTyp whichVar;
- #endif
- /*Takes a snapshot of object*/
- {
- ObjPtr list;
- ObjPtr retVal;
-
- /*Make the snap vars*/
- list = NewList();
- PostfixList(list, NewSymbol(whichVar));
-
- retVal = NewObject(snapshotClass, 0L);
- SetVar(retVal, REPOBJ, object);
- SetVar(retVal, SNAPVARS, list);
- if (list)
- {
- ThingListPtr runner;
-
- runner = LISTOF(list);
- while (runner)
- {
- NameTyp id;
-
- id = GetSymbolID(runner -> thing);
- if (id)
- {
- MakeVar(object, id);
- SetVar(retVal, id, GetVar(object, id));
- }
- runner = runner -> next;
- }
- }
- SetVar(retVal, NAME, GetVar(object, NAME));
- SetVar(retVal, REPCLASSID, GetVar(object, CLASSID));
-
- return retVal;
- }
-
- #ifdef PROTO
- Bool EqualSnapshots(ObjPtr snap1, ObjPtr snap2)
- #else
- Bool EqualSnapshots(snap1, snap2)
- ObjPtr snap1, snap2;
- #endif
- /*Returns true iff the two snapshots are equal. BUGS--assumes that snapvars
- are equal, so only use this on something like a track control where the
- var group is constant*/
- {
- ObjPtr var1, var2;
- ThingListPtr runner;
-
- var1 = GetVar(snap1, REPOBJ);
- var2 = GetVar(snap2, REPOBJ);
- if (var1 != var2) return false;
-
- var1 = GetVar(snap1, SNAPVARS);
- if (var1)
- {
- for (runner = LISTOF(var1); runner; runner = runner -> next)
- {
- var1 = GetVar(snap1, GetSymbolID(runner -> thing));
- var2 = GetVar(snap2, GetSymbolID(runner -> thing));
- if (!Equal(var1, var2)) return false;
- }
- }
-
- return true;
- }
-
- #ifdef PROTO
- void PullSnapVars(ObjPtr newObject, ObjPtr oldObject)
- #else
- void TakeSnapshot(newObject, oldObject)
- ObjPtr newObject, oldObject;
- #endif
- /*Transters the snap vars of newObject from corresponding values in oldObject*/
- {
- ObjPtr list;
- ObjPtr retVal;
-
- /*Make the snap vars*/
- list = AssembleSnapVars(newObject);
-
- if (list)
- {
- ThingListPtr runner;
-
- runner = LISTOF(list);
- while (runner)
- {
- NameTyp id;
-
- id = GetSymbolID(runner -> thing);
- if (id)
- {
- SetVar(newObject, id, GetVar(oldObject, id));
- }
- runner = runner -> next;
- }
- }
- }
-
- #ifdef PROTO
- void ApplySnapshotTo(ObjPtr snapshot, ObjPtr object)
- #else
- void ApplySnapshotTp(snapshot, object)
- ObjPtr snapshot;
- ObjPtr object;
- #endif
- /*Applies snapshot to an object*/
- {
- ObjPtr list;
-
- list = GetVar(snapshot, SNAPVARS);
-
- if (list && object)
- {
- ThingListPtr runner;
- ObjPtr value;
-
- runner = LISTOF(list);
- while (runner)
- {
- NameTyp id;
-
- id = GetSymbolID(runner -> thing);
- if (id)
- {
- if (id == VALUE)
- {
- value = GetVar(snapshot, VALUE);
- SetValue(object, value);
- }
- else
- {
- SetVar(object, id, GetVar(snapshot, id));
- }
- }
- runner = runner -> next;
- }
- ImInvalid(object);
- }
- }
-
- #ifdef PROTO
- void ApplySnapshot(ObjPtr snapshot)
- #else
- void ApplySnapshot(snapshot)
- ObjPtr snapshot;
- #endif
- /*Applies snapshot to its object*/
- {
- ObjPtr object;
-
- object = GetVar(snapshot, REPOBJ);
- ApplySnapshotTo(snapshot, object);
- }
-
- #ifdef PROTO
- ObjPtr InterpSimpleObjects(ObjPtr var1, ObjPtr var2, real weight)
- #else
- ObjPtr InterpSimpleObjects(var1, var2, weight)
- ObjPtr var1, var2;
- real weight;
- #endif
- /*Interpolates between two simple objects according to weight. 0 means
- all var1, and 1 means all var2. If it can't interpolate, prints out
- an error message and does a weighted choice.*/
- {
- if (IsInt(var1) && IsInt(var2))
- {
- /*Interpolation of integers*/
- real r1, r2;
-
- r1 = (real) GetInt(var1);
- r2 = (real) GetInt(var2);
-
- return NewInt((int) floor(r2 * weight + r1 * (1.0 - weight) + 0.5));
- }
- else if ((IsReal(var1) || IsInt(var1)) && (IsReal(var2) || IsInt(var2)))
- {
- /*Interpolation of real numbers*/
- real r1, r2;
-
- r1 = GetReal(var1);
- r2 = GetReal(var2);
-
- return NewReal(r2 * weight + r1 * (1.0 - weight));
- }
- else if (IsString(var1) && IsString(var2))
- {
- /*Interpolation of strings.*/
- return (weight >= 0.5) ? var2 : var1;
- }
- else if (IsRealArray(var1) && IsRealArray(var2))
- {
- /*Interpolation of real arrays*/
- long k;
- long length;
- real *el1, *el2, *el3;
- ObjPtr retVal;
-
- /*Make sure that the dimensions are the same*/
- if (RANK(var1) != RANK(var2))
- {
- ReportError("InterpSimpleObjects", "Array rank mismatch");
- return (weight >= 0.5) ? var2 : var1;
- }
-
- length = 1;
- for (k = 0; k < RANK(var1); ++k)
- {
- if (DIMS(var1)[k] != DIMS(var2)[k])
- {
- ReportError("InterpSimpleObjects", "Array dimension mismatch");
- return (weight >= 0.5) ? var2 : var1;
- }
- length *= DIMS(var1)[k];
- }
- el1 = ELEMENTS(var1);
- el2 = ELEMENTS(var2);
-
- retVal = NewArray(AT_REAL, RANK(var1), DIMS(var1));
- if (!retVal)
- {
- return (weight >= 0.5) ? var2 : var1;
- }
-
- el3 = ELEMENTS(retVal);
-
- for (k = 0; k < length; ++k)
- {
- if (el1[k] == missingData || el1[k] == plusInf || el1[k] == minusInf ||
- el2[k] == missingData || el2[k] == plusInf || el2[k] == minusInf)
- {
- el3[k] = (weight >= 0.5) ? el2[k] : el1[k];
- }
- else
- {
- el3[k] = weight * el2[k] + (1.0 - weight) * el1[k];
- }
- }
- return retVal;
- }
- else if (IsObject(var1) && IsObject(var2))
- {
- /*Just two objects*/
- return (weight >= 0.5) ? var2 : var1;
- }
- else
- {
- char errmes[256];
- sprintf(errmes, "Cannot interpolate between values %x and %x\n", var1, var2);
- ReportError("InterpSimpleObjects", errmes);
- return (weight >= 0.5) ? var2 : var1;
- }
- }
-
- #ifdef PROTO
- ObjPtr InterpSnapshots(ObjPtr snap1, ObjPtr snap2, real weight)
- #else
- ObjPtr InterpSnapshots(snap1, snap2, weight)
- ObjPtr snap1, snap2;
- real weight;
- #endif
- /*Returns a weighted interpolation of two snapshots. Assumes that they have
- the same variables.*/
- {
- ObjPtr variables;
- ObjPtr var1, var2;
- ObjPtr retVal;
- ThingListPtr runner;
-
- retVal = NewObject(snapshotClass, 0L);
-
- /*Make the snap vars*/
- variables = GetListVar("InterpSnapshots", snap1, SNAPVARS);
- if (!variables) return ObjFalse;
- SetVar(retVal, SNAPVARS, CopyList(variables));
-
- SetVar(retVal, REPOBJ, GetVar(snap1, REPOBJ));
- SetVar(retVal, NAME, GetVar(snap1, NAME));
- SetVar(retVal, REPCLASSID, GetVar(snap1, CLASSID));
-
- /*Interpolate the variables*/
- runner = LISTOF(variables);
- while (runner)
- {
- NameTyp id;
-
- id = GetSymbolID(runner -> thing);
- var1 = GetVar(snap1, id);
- var2 = GetVar(snap2, id);
- SetVar(retVal, id, InterpSimpleObjects(var1, var2, weight));
-
- runner = runner -> next;
- }
- return retVal;
- }
-
- #ifdef PROTO
- void LogSnapshot(ObjPtr object)
- #else
- void LogSnapshot(object)
- ObjPtr object;
- #endif
- /*Logs a snapshot of object*/
- {
- ObjPtr list;
- ObjPtr retVal;
- Bool needsWindow = false;
-
- needsWindow = MakeObjectName(tempStr, object);
-
- if (needsWindow)
- {
- Log("begin snapshot ");
- Log(tempStr);
- Log("\n");
- }
- else
- {
- LogNoWindow("begin snapshot ");
- LogNoWindow(tempStr);
- LogNoWindow("\n");
- }
-
- /*Make the snap vars*/
- list = AssembleSnapVars(object);
-
- if (list)
- {
- ThingListPtr runner;
- char cmd[256];
- char *s;
-
- runner = LISTOF(list);
- while (runner)
- {
- NameTyp id;
- ObjPtr value;
-
- id = GetSymbolID(runner -> thing);
- if (id)
- {
- value = GetVar(object, id);
- if (IsInt(value))
- {
- sprintf(cmd, " set variable %s (int) ", GetInternalString(id));
- }
- else
- {
- sprintf(cmd, " set variable %s ", GetInternalString(id));
- }
- s = &(cmd[0]);
- while (*s) ++s;
- PrintScriptObject(s, value);
- while (*s) ++s;
- *s++ = '\n';
- *s = 0;
- if (needsWindow)
- {
- Log(cmd);
- }
- else
- {
- LogNoWindow(cmd);
- }
- }
- runner = runner -> next;
- }
- }
- if (needsWindow)
- {
- Log("end snapshot\n");
- }
- else
- {
- LogNoWindow("end snapshot\n");
- }
- }
-
- #ifdef PROTO
- void SubsumeObjIntoDatabase(ObjPtr object)
- #else
- void SubsumeObjIntoDatabase(object)
- ObjPtr object;
- #endif
- /*Subsumes an object into the database. This means---
- 1) Looks for an object with the same name and CLASS_ID
- 2) If found,
- Replaces the object in the database with this object, but takes a
- snapshot of the old object from the new object's snapvars and
- applies it to the new object.
- 3) If not found, just adds this object to the database.
- */
- {
- ObjPtr keyList;
- ObjPtr resultList;
-
- keyList = NewList();
- PostfixList(keyList, NewSymbol(NAME));
- MakeVar(object, NAME);
- PostfixList(keyList, GetVar(object, NAME));
- PostfixList(keyList, NewSymbol(CLASSID));
- MakeVar(object, CLASSID);
- PostfixList(keyList, GetVar(object, CLASSID));
- if (resultList = SearchDatabase(keyList))
- {
- if (LISTOF(resultList))
- {
- PullSnapVars(object, LISTOF(resultList) -> thing);
- DeleteObjFromDatabase(LISTOF(resultList) -> thing);
- }
- }
- AddObjToDatabase(object);
- }
-
- #ifdef PROTO
- void ApplySavedSettings(ObjPtr object)
- #else
- void ApplySavedSettings(object)
- ObjPtr object;
- #endif
- /*Applies the saved settings to object*/
- {
- ObjPtr directory;
-
- directory = GetSettingsDirectory();
-
- ReadObjectControls(object, directory, false);
- }
-
- #ifdef PROTO
- ObjPtr GetSettingsDirectory(void)
- #else
- ObjPtr GetSettingsDirectory()
- #endif
- /*Returns a string of the settings directory, which by default is
- ~/scianSettings. Creates the directory if need be*/
- {
- char dirName[256];
- struct stat buf;
- int notThere;
-
- sprintf(dirName, "%s/%s", getenv("HOME"), ".scianSettings");
- notThere = stat(dirName, &buf);
- if (notThere)
- {
- FILE *outFile;
-
- /*Have to create it*/
- if (mkdir(dirName, S_IREAD | S_IWRITE | S_IEXEC))
- {
- /*Failed to create*/
- ReportError("GetSettingsDirectory", "Cannot create directory");
- return NULLOBJ;
- }
- notThere = stat(dirName, &buf);
- if (notThere)
- {
- /*Still not there, return null*/
- ReportError("GetSettingsDirectory", "Tried create directory, but it's not there");
- return NULLOBJ;
- }
-
- /*Put in a README*/
- strcpy(tempStr, dirName);
- strcat(tempStr, "/README");
- outFile = fopen(tempStr, "w");
- if (!outFile)
- {
- ReportError("GetSettingsDirectory", "Cannot create files in directory");
- return NULLOBJ;
- }
- fprintf(outFile, "This directory is used to save settings from within SciAn.\n");
- fclose(outFile);
- }
-
- /*Directory exists, see if it's OK*/
- if ((buf.st_mode & S_IFMT) == S_IFDIR)
- {
- /*It's OK*/
- return NewString(dirName);
- }
- ReportError("GetSettingsDirectory", "Problem using settings directory");
- return NULLOBJ;
- }
-
- ObjPtr SaveSnapshotControls(object)
- ObjPtr object;
- /*Saves an object's controls from a snapshot*/
- {
- ObjPtr directory;
-
- directory = GetSettingsDirectory();
-
- SaveObjectControls(object, directory);
- return ObjTrue;
- }
-
- ObjPtr LogSnapshotControls(object)
- ObjPtr object;
- /*Logs all the controls for an object*/
- {
- LogSnapshot(object);
- return ObjTrue;
- }
-
- #ifdef PROTO
- void InitSnapshots(void)
- #else
- void InitSnapshots()
- #endif
- /*Initializes snapshot system*/
- {
- snapshotClass = NewObject(NULLOBJ, 0L);
- AddToReferenceList(snapshotClass);
- SetVar(snapshotClass, CLASSID, NewInt(CLASS_SNAPSHOT));
- classClasses[CLASS_SNAPSHOT] = snapshotClass;
- }
-
- #ifdef PROTO
- void KillSnapshots(void)
- #else
- void KillSnapshots()
- #endif
- /*Kills the snapshot system*/
- {
- RemoveFromReferenceList(snapshotClass);
- }
-
-